package com.ruoyi.utils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ruoyi.pojo.Loans;
import com.ruoyi.vo.Repayment;
import org.springframework.context.annotation.Configuration;

@Configuration
public class LoansUtils {

    /**
     * sum:贷款本金
     * periodsNum:还款月数
     * returned:当前月数
     * rate:月利率
     */
    //等额本金 本月应还贷款
    public static Repayment equalityEorpus(Integer sum,Integer periodsNum,Integer returned,Double rate){
        //获取一个月应还的本金数
        double monthNum = sum/(double)periodsNum;
        //剩余本金
        double returnedNum = sum - (returned * monthNum);
        //本月应还利息
        double interests = returnedNum * rate;
        Repayment report = new Repayment();
        report.setMonthNum(monthNum);
        report.setReturned(returned);
        report.setRate(rate);
        report.setInterests(interests);
        report.setSumTotal(interests + monthNum);
        return report;
    }

    /**
     * sum:贷款本金
     * periodsNum:还款月数
     * returned:当前月数
     * rate:月利率
     */
    //等额本息 本月还款金额
    public static Double averageCapitalPlusInterest(Integer sum,Integer periodsNum,Integer returned,Double rate){
        Double doubleRate = 1 + rate;
        for (int i = 0; i < periodsNum; i++) {
            doubleRate = doubleRate * doubleRate;
        }
        Double doubleSum = sum * rate * doubleRate;
        Double doubleRepayment = doubleSum / (doubleRate - 1);
        System.out.println("本月总还款金额:" + doubleRepayment);
        return doubleRepayment;
    }

    /**
     * 每月偿还本金和利息
     * <p>
     * 公式：每月偿还本息=〔贷款本金×月利率×(1＋月利率)＾还款月数〕÷〔(1＋月利率)＾还款月数-1〕
     *
     * @param invest     总借款额（贷款本金,单位分）
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还本金和利息(入1 单位分)
     */
    public static long getPerMonthPrincipalInterest(long invest, double yearRate, int totalMonth) {
        double monthRate = yearRate / 12;
        double perMonthPrincipalInterest = invest * (monthRate * Math.pow(1 + monthRate, totalMonth))/(Math.pow(1 + monthRate, totalMonth) - 1);
        return new BigDecimal(perMonthPrincipalInterest).setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
    }

    /**
     * 等额本息的每月偿还利息
     * <p>
     * 公式：每月偿还利息=贷款本金×月利率×〔(1+月利率)^还款月数-(1+月利率)^(还款月序号-1)〕÷〔(1+月利率)^还款月数-1〕
     *
     * @param invest     总借款额（贷款本金,分）
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还利息(入1 单位分)
     */
    public static Map<Integer, Long> getPerMonthInterest(long invest, double yearRate, int totalMonth) {
        Map<Integer, Long> map = new HashMap<>();
        double monthRate = yearRate / 12;
        double monthInterest;
        for (int i = 1; i < totalMonth + 1; i++) {
            double multiply = invest * monthRate;
            double sub = Math.pow(1 + monthRate, totalMonth) - Math.pow(1 + monthRate, i - 1);
            monthInterest = multiply * sub/(Math.pow(1 + monthRate, totalMonth) - 1);
            map.put(i, new BigDecimal(monthInterest).setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
        }
        return map;
    }

    /**
     * 等额本息的每月偿还本金（月还本息-月还利息）
     *
     * @param invest     总借款额（贷款本金,分）
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还本金(取整舍 单位分)
     */
    public static Map<Integer, Long> getPerMonthPrincipal(long invest, double yearRate, int totalMonth) {
        double monthRate = yearRate / 12;
        double monthIncome = invest * monthRate * Math.pow(1 + monthRate, totalMonth)
                /(Math.pow(1 + monthRate, totalMonth) - 1);
        long perMonthPrincipalInterest = new BigDecimal(monthIncome).setScale(0, BigDecimal.ROUND_HALF_UP).longValue();

        Map<Integer, Long> mapPrincipal = new HashMap<>();
        double monthInterest;
        for (int i = 1; i < totalMonth + 1; i++) {
            Double multiply = invest * monthRate;
            double sub = (Math.pow(1 + monthRate, totalMonth)) - (Math.pow(1 + monthRate, i - 1));
            monthInterest = multiply* sub/(Math.pow(1 + monthRate, totalMonth) - 1);
            long monthInterestL = new BigDecimal(monthInterest).setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
            mapPrincipal.put(i, perMonthPrincipalInterest-monthInterestL);
        }
        return mapPrincipal;
    }

    /**
     * 等额本息的总利息
     *
     * @param invest     总借款额（贷款本金）
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 总利息 (单位分)
     */
    public static long getInterestCount(long invest, double yearRate, int totalMonth) {
        long count = 0;
        Map<Integer, Long> mapInterest = getPerMonthInterest(invest, yearRate, totalMonth);

        for (Map.Entry<Integer, Long> entry : mapInterest.entrySet()) {
            count = count + entry.getValue();
        }
        return count;
    }

    //等额本金还款计算方式
    public static Map<String,Object> capital(Integer principal, Loans loans){
        Map<String,Object> map = new HashMap<>();
        List<Repayment> repaymentList = new ArrayList<>();
        Double sum = 0.0;
        Integer numbe = loans.getNumbe();
        Long interestrate = loans.getInterestrate();
        Double dinterestrate = (double)interestrate;
        dinterestrate = (dinterestrate * 0.0001) / numbe;
        for (Integer i = 1; i <= numbe; i++) {
            Repayment repayment = LoansUtils.equalityEorpus(principal, numbe, i, dinterestrate);
            repaymentList.add(repayment);
            sum += repayment.getSumTotal();
        }
        map.put("repaymentList", repaymentList);
        map.put("sum", sum);
        return map;
    }

    //等额本息计算方式
    public static Map<String,Object> interests(Integer principal, Loans loans) {
        Map<String,Object> map = new HashMap<>();
        List<Repayment> repaymentList = new ArrayList<>();
        Double sum = 0.0;
        //获取贷款信息
        //获取借款期数
        Integer numbe = loans.getNumbe();
        //获取年利率
        Long interestrate = loans.getInterestrate();
        Double dinterestrate = interestrate * 0.0001;
        double month = dinterestrate / numbe;
        //计算贷款金额
        long perMonthPrincipalInterest = LoansUtils.getPerMonthPrincipalInterest(principal, dinterestrate, numbe);
        System.out.println("等额本息---每月还款本息：" + perMonthPrincipalInterest);
        Map<Integer, Long> mapInterest = LoansUtils.getPerMonthInterest(principal, dinterestrate, numbe);
        System.out.println("等额本息---每月还款利息：" + mapInterest);
        Map<Integer, Long> mapPrincipal = LoansUtils.getPerMonthPrincipal(principal, dinterestrate, numbe);
        System.out.println("等额本息---每月还款本金：" + mapPrincipal);
        long count = LoansUtils.getInterestCount(principal, dinterestrate, numbe);
        System.out.println("等额本息---总利息：" + count);


        for (int i = 1; i < numbe + 1; i++) {
            Repayment report = new Repayment();
            if (i < numbe) {
                report.setMonthNum(mapPrincipal.get(i));
                report.setReturned(numbe);
                report.setRate(month);
                report.setInterests(mapInterest.get(i));
                report.setSumTotal(mapPrincipal.get(i) + mapInterest.get(i));
                System.out.println("等额本息---" + i + "月还款本金:" + mapPrincipal.get(i) + ",还款利息:" + mapInterest.get(i));
                principal = (int) (principal - mapPrincipal.get(i));
            } else {
                report.setMonthNum(principal);
                report.setReturned(numbe);
                report.setRate(month);
                report.setInterests(perMonthPrincipalInterest - principal);
                report.setSumTotal(mapPrincipal.get(i) + mapInterest.get(i));
                System.out.println("等额本息---" + i + "月还款本金:" + principal + ",还款利息:" + (perMonthPrincipalInterest - principal));
            }
            repaymentList.add(report);
        }
        sum = (double) (perMonthPrincipalInterest * numbe);
        map.put("list",repaymentList);
        map.put("sum", sum);
        return map;
    }

}
